package com.jappit.runtracker.screens;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.midlet.MIDletStateChangeException;

import com.jappit.runtracker.RunTracker;
import com.jappit.runtracker.data.DataManager;
import com.jappit.runtracker.data.RunSetHandler;
import com.jappit.runtracker.model.Run;
import com.jappit.runtracker.utils.AppUtils;
import com.jappit.runtracker.utils.FormatUtils;
import com.nokia.maps.common.ApplicationContext;
import com.nokia.maps.common.GeoCoordinate;
import com.nokia.maps.map.MapCanvas;
import com.nokia.maps.map.MapContainer;
import com.nokia.maps.map.MapMarker;
import com.nokia.maps.map.MapObject;
import com.nokia.maps.map.MapPolyline;
import com.nokia.maps.map.MapShapeType;
import com.nokia.maps.map.MapStandardMarker;
import com.nokia.maps.map.Point;
import com.nokia.maps.routing.GeoPosition;
import com.nokia.maps.routing.PositionListener;
import com.nokia.maps.routing.PositioningManager;

public class NewRunScreen extends MapCanvas implements PositionListener, CommandListener
{
	PositioningManager positioningManager = null;
	
	GeoPosition currentPosition = null;
	
	MapContainer pathContainer = null;
	
	Command startCommand, stopCommand, backCommand, detailCommand;
	
	Run run = null;
	
	Timer secsTimer = null;
	
	RunSetHandler handler = null;
	
	boolean runCanceled = false;
	
	MapObject runnerMarker = null;
	
	public NewRunScreen(RunSetHandler handler)
	{
		super(Display.getDisplay(AppUtils.getInstance().getMIDlet()));
		
		this.handler = handler;
		
		run = new Run();
		
		pathContainer = this.getMapFactory().createMapContainer(false);
        
		this.getMapDisplay().addMapObject(pathContainer);
		//this.getMapDisplay().setZoomLevel(this.getMapDisplay().getMaxZoomLevel() - 2, 0, 0);
            
        positioningManager = PositioningManager.getInstance();
        positioningManager.setListener(this);
        positioningManager.startPositioning();
        
        this.addCommand(backCommand = new Command("Back", Command.BACK, 1));
        this.setCommandListener(this);
        
        try
        {
        	runnerMarker = this.getMapFactory().createMapMarker(this.getMapDisplay().getCenter(), Image.createImage("/I_RUNNER.png"));
        	
        	((MapMarker)runnerMarker).setAnchor(new Point(-16, -16));
        }
        catch(Exception e)
        {
        	runnerMarker = this.getMapFactory().createStandardMarker(this.getMapDisplay().getCenter(), 32, "R", MapShapeType.baloon);
        }  
    }
	protected void paint(Graphics graphics)
	{
		super.paint(graphics);
		
		Font mainFont = Font.getDefaultFont();
		int fontHeight = mainFont.getHeight();
		
		graphics.setColor(0x000000);
		graphics.fillRect(0, 0, getWidth(), fontHeight + 4);
		
		graphics.setColor(0xff0000);
		
		if(currentPosition == null)
		{
			graphics.drawString("Waiting GPS", getWidth() / 2, 2, Graphics.TOP | Graphics.HCENTER);
		}
		else if(run.isStarted())
		{
			graphics.drawString(FormatUtils.formatDuration(run.getDuration()), 2, 2, Graphics.TOP | Graphics.LEFT);
			
			graphics.drawString(FormatUtils.formatDistance(run.getDistance()), getWidth() - 2, 2, Graphics.TOP | Graphics.RIGHT);
		}
	}
	private void updateTime()
	{
		repaint();
	}
    public void commandAction(Command c, Displayable d)
    {
    	if(c == startCommand)
    	{
    		run.start();
    		
    		secsTimer = new Timer();
    		secsTimer.schedule(new TimerTask() {
				
				public void run() {
					updateTime();
				}
			}, 1000, 1000);
    		
    		this.getMapDisplay().addMapObject(runnerMarker);
    		
    		this.removeCommand(startCommand);
    		this.addCommand(stopCommand = new Command("Stop", Command.OK, 1));
    	}
    	else if(c == stopCommand)
    	{
    		secsTimer.cancel();
    		
    		this.removeCommand(stopCommand);
    		this.addCommand(detailCommand = new Command("Details", Command.OK, 1));
    		
    		positioningManager.stopPositioning();
    	}
    	else if(c == backCommand)
    	{
    		runCanceled = true;
    		
    		positioningManager.stopPositioning();
    		
    		AppUtils.getInstance().gotoPreviousScreen();
    	}
    	else if(c == detailCommand)
    	{
    		AppUtils.getInstance().gotoScreen(new RunDetailsScreen(run), true);
    	}
    }
    
    public void positioningStarted()
    {
    	pathContainer.removeAllMapObjects();
    }
    public void positioningUpdated(GeoPosition position)
    {
    	if(run != null && !runCanceled && !run.isEnded())
    	{
    		GeoCoordinate newCoordinate = position.getCoordinate();
        	
        	if(currentPosition == null)
        	{
        		this.getMapDisplay().setZoomLevel(this.getMapDisplay().getMaxZoomLevel() / 2, 0, 0);
        		
        		this.addCommand(startCommand = new Command("Start", Command.OK, 1));
        	}
        	
        	if(run.isStarted())
        	{
        		if(run.getLastCoordinate() != null)
        		{
        			MapPolyline line = this.getMapFactory().createMapPolyline(new GeoCoordinate[]{
        				run.getLastCoordinate(), newCoordinate
                	});
            		
            		pathContainer.addMapObject(line);
        		}
        		
        		updateMarker(newCoordinate);
        		
        		run.addCoordinate(newCoordinate);
        	}
        	currentPosition = position;
        	
        	this.getMapDisplay().setCenter(position.getCoordinate());
        	
        	this.mapContentUpdated();
    	}
    }
    private void updateMarker(GeoCoordinate coordinate)
    {
    	if(runnerMarker instanceof MapMarker)
    	{
    		((MapMarker)runnerMarker).setCoordinate(coordinate);
    	}
    	else if(runnerMarker instanceof MapStandardMarker)
    	{
    		((MapStandardMarker)runnerMarker).setCoordinate(coordinate);
    	}
    }
    public void positioningEnded()
    {
    	if(run != null && !runCanceled)
    	{
        	try
        	{
        		run.stop();
        		
        		DataManager.getInstance().addRun(run);
        		
        		handler.runSetModified();
        	}
        	catch(Exception e)
        	{
        		e.printStackTrace();
        		AppUtils.getInstance().showError(e.getMessage());
        	}
    	}
    }
    public void positioningError(Throwable error)
    {
    	AppUtils.getInstance().showError(error.getMessage());
    }
}
